<?php


class XiaoWei
{
    private $mch_id;
    private $key;

    public function __construct($mch_id, $key, $url)
    {
        $this->url = rtrim($url, '/') . '/pay';
        $this->mch_id = $mch_id;
        $this->key = $key;
    }

    public function notify()
    {
        if (isset($_POST['sign'])) {
            if ($_POST['sign'] === $this->getSign($_POST)) {
                return $_POST;
            }
        }
        return false;
    }

    public function query($out_trede_no)
    {
        $params = [
            'mch_id' => $this->mch_id,
            'out_trade_no' => $out_trede_no
        ];
        $params['sign'] = $this->getSign($params);
        return $this->request($this->url . '/query', $params);
    }

    public function order($out_trede_no, $total_fee, $pt, $channel, $notify_url = '', $subject = '', $openid = null, $sub_mch_id = null)
    {
        $params = [
            'mch_id' => $this->mch_id,
            'out_trade_no' => $out_trede_no,
            'total_fee' => $total_fee,
            'pt' => $pt,
            'channel' => $channel,
            'notify_url' => $notify_url,
            'subject' => $subject
        ];
        if ($openid) {
            $params['openid'] = $openid;
        }
        if ($sub_mch_id) {
            $params['sub_mch_id'] = $sub_mch_id;
        }
        $params['sign'] = $this->getSign($params);
        return $this->request($this->url . '/order', $params);
    }

    public function getOpenidUrl($url)
    {
        $params = [
            'mch_id' => $this->mch_id,
            'callback' => $url
        ];
        $params['sign'] = $this->getSign($params);
        return $this->url . '/openid?' . self::arr2str($params);
    }

    private static function arr2str($param)
    {
        $str = "";
        foreach ($param as $k => $v) {
            $str .= "&{$k}=" . urlencode($v);
        }
        return trim($str, '&');
    }

    private function getSign($params)
    {
        $signPars = "";
        ksort($params);
        foreach ($params as $k => $v) {
            if ("sign" !== $k && "" !== trim($v) && $v !== null) {
                $signPars .= $k . "=" . $v . "&";
            }
        }
        $signPars .= "key=" . $this->key;
        $sign = strtoupper(md5($signPars));
        return $sign;
    }

    private function request($url, $params = [])
    {
        list($body, $err) = $this->getCurl($url, $params);
        if ($body) {
            if ($ret = json_decode($body, true)) {
                if ($ret['status'] === 0) {
                    return [$ret, null];
                } else {
                    return [false, $ret['message']];
                }
            } else {
                return [false, '解析JSON数据失败'];
            }
        } else {
            return [false, $err];
        }
    }


    private function getCurl($url, $post = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if ($post) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        }
        curl_setopt($ch, CURLOPT_ENCODING, "gzip");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $ret = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);
        if ($err) {
            return [false, $err];
        } else {
            return [$ret, null];
        }
    }

}